package com.bbcare.comm;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;



import org.apache.log4j.Logger;


/**
 * 日期时间工具类
 *
 */
public class DateTimeUtil {

	private static final Logger logger = Logger.getLogger(DateTimeUtil.class);

	private final static String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };

	/**
	 * yyyy-MM-dd
	 */
	public static int yyyy_MM_dd = 0;
	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static int yyyy_MM_dd_HH_mm_ss = 1;
	/**
	 * HH:mm:ss
	 */
	public static int HH_mm_ss = 2;
	/**
	 * yyyyMMddHHmmss
	 */
	public static int yyyyMMddHHmmss = 3;
	/**
	 * yyyyMMddHHmmssSS
	 */
	public static int yyyyMMddHHmmssSSS = 4;
	/**
	 * yyyy年MM月dd日
	 */
	public static int c_yyyy_MM_dd_ = 5;
	/**
	 * yyyy年MM月dd日HH时mm分ss秒
	 */
	public static int c_yyyy_MM_dd_HH_mm_ss_ = 6;
	/**
	 * yyyy
	 */
	public static int yyyy = 7;
	/**
	 * MM
	 */
	public static int MM = 8;
	/**
	 * dd
	 */
	public static int dd = 9;
	/**
	 * yyyyMMdd
	 */
	public static int yyyyMMdd = 10;
	/**
	 * yyyy-MM
	 */
	public static int yyyy_MM = 11;
	/**
	 * yyyy年MM月dd日 EE
	 */
	public static int c_yyyy_MM_dd_EE = 12;
	/**
	 * yyyy/MM/dd HH:mm:ss
	 */
	public static int x_yyyy_MM_dd_HH_mm_ss = 13;

	/**
	 * HHmmss
	 */
	public static int HHmmss = 14;

	/**
	 * HHmmssSS
	 */
	public static int HHmmssSSS = 15;
	/**
	 * HH:mm
	 */
	public static int HH_mm = 17;
	/**
	 * yyyy-MM-dd HH:mm
	 */
	public static int yyyy_MM_dd_HH_mm = 18;
	/**
	 * 格式化日期样式
	 * @param caseNum
	 * @return
	 */
	public static SimpleDateFormat getDateFormat(int caseNum) {
		SimpleDateFormat dateFormat = null;
		switch (caseNum) {
		case 0:
			dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			break;
		case 1:
			dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			break;
		case 2:
			dateFormat = new SimpleDateFormat("HH:mm:ss");
			break;
		case 3:
			dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
			break;
		case 4:
			dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
			break;
		case 10:
			dateFormat = new SimpleDateFormat("yyyyMMdd");
			break;
		case 5:
			dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
			break;
		case 6:
			dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
			break;
		case 7:
			dateFormat = new SimpleDateFormat("yyyy");
			break;
		case 8:
			dateFormat = new SimpleDateFormat("MM");
			break;
		case 9:
			dateFormat = new SimpleDateFormat("dd");
			break;
		case 11:
			dateFormat = new SimpleDateFormat("yyyy-MM");
			break;
		case 12:
			dateFormat = new SimpleDateFormat("yyyy年MM月dd日 EE");
			break;
		case 13:
			dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
			break;
		case 14:
			dateFormat = new SimpleDateFormat("HHmmss");
			break;
		case 15:
			dateFormat = new SimpleDateFormat("HHmmssSSS");
			break;
		case 16:
			dateFormat = new SimpleDateFormat("yyyy/MM/dd");
			break;
		case 17:
			dateFormat = new SimpleDateFormat("HH:mm");
			break;
		case 18:
			dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			break;
		default:
			break;
		}
		return dateFormat;
	}

	/**
	 * 把日期转换为字符串
	 * @param date
	 * @param caseNum
	 * @return
	 */
	public static String formatDate(Date date, int caseNum) {
		String dateStr = null;
		SimpleDateFormat dateFormat = getDateFormat(caseNum);
		dateStr = dateFormat.format(date);
		return dateStr;
	}

	/**
	 * 把字符串转换为日期
	 * @param dateStr
	 * @param caseNum
	 * @return
	 */
	public static Date parseDate(String dateStr, int caseNum) {
		Date date = null;
		try {
			SimpleDateFormat dateFormat = getDateFormat(caseNum);
			date = dateFormat.parse(dateStr);
		} catch (Exception e) {
			logger.error("parseDate error:", e);
		}
		return date;
	}
	
	public static Calendar parseCalendar(String dateStr, int caseNum) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(parseDate(dateStr,caseNum));
		return calendar;
	}

	/**
	 * 获取当前时间的字符串形式
	 * @param caseNum
	 * @return
	 * @throws Exception
	 */
	public static String getNowDateStr(int caseNum) {
		Date date = new Date();
		SimpleDateFormat dateFormat = getDateFormat(caseNum);
		String dateStr = dateFormat.format(date);
		return dateStr;
	}

	/**
	 * 得到年份
	 * @param c
	 * @return
	 */
	public static int getYear(Calendar c) {
		return c.get(Calendar.YEAR);
	}

	/**
	 * 得到当前年份
	 * @return
	 */
	public static int getYear() {
		return Calendar.getInstance().get(Calendar.YEAR);
	}

	/**
	 * 得到月份
	 * @param c
	 * @return
	 */
	public static int getMonth(Calendar c) {
		return c.get(Calendar.MONTH);
	}

	/**
	 * 得到当前月份
	 * @return
	 */
	public static int getMonth() {
		return Calendar.getInstance().get(Calendar.MONTH);
	}

	/**
	 * 得到日
	 * @param c
	 * @return
	 */
	public static int getDate(Calendar c) {
		return c.get(Calendar.DATE);
	}

	/**
	 * 得到当前日
	 * @return
	 */
	public static int getDate() {
		return Calendar.getInstance().get(Calendar.DATE);
	}

	/**
	 * 得到星期
	 * @param c
	 * @return
	 */
	public static int getDay(Calendar c) {
		return c.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * 得到当前星期  1星期日,2星期一...
	 * @return
	 */
	public static int getDay() {
		return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
	}
	
	/**
	 * 得到指定日期date一周内周一到周日的日期
	 * @param caseNum
	 * @param day 1星期一...7星期日
	 * @return
	 */
	public static String getWeekDate(String date,int caseNum, int day) {
		String rstr = "";
		int num = getDay(parseCalendar(date, caseNum));
		if (num == 1) {// 给定的日期是本周星期日
			rstr = addDate(date, caseNum, Calendar.DATE , day - 7);
		} else if (num == 2) {// 给定的日期是本周星期1
			rstr = addDate(date, caseNum, Calendar.DATE , day - 1);
		} else if (num == 3) {// 给定的日期是本周星期2
			rstr = addDate(date, caseNum, Calendar.DATE , day - 2);
		} else if (num == 4) {// 给定的日期是本周星期3
			rstr = addDate(date, caseNum, Calendar.DATE , day - 3);
		} else if (num == 5) {// 给定的日期是本周星期4
			rstr = addDate(date, caseNum, Calendar.DATE , day - 4);
		} else if (num == 6) {// 给定的日期是本周星期5
			rstr = addDate(date, caseNum, Calendar.DATE , day - 5);
		} else if (num == 7) {// 给定的日期是本周星期6
			rstr = addDate(date, caseNum, Calendar.DATE , day - 6);
		}
		return rstr;
	}
	
	/**
	 * 得到本周内周一到周日的日期
	 * @param day
	 * @return
	 */
	public static String getNowWeekDate(int day) {
		return getWeekDate(getNowDateStr(0),0,day);
	}

	/**
	 * 得到星期
	 * @param c
	 * @return
	 */
	public static String getChineseDay(Calendar c) {
		return dayNames[getDay(c) - 1];
	}

	/**
	 * 得到当前星期（中文）
	 * @return
	 */
	public static String getChineseDay() {
		return dayNames[getDay() - 1];
	}

	/**
	 * 得到小时
	 * @param c
	 * @return
	 */
	public static int getHour(Calendar c) {
		return c.get(Calendar.HOUR);
	}

	/**
	 * 得到当前小时
	 * @return
	 */
	public static int getHour() {
		return Calendar.getInstance().get(Calendar.HOUR);
	}
	
	/**
	 * 得到当前小时 (24小时制)
	 * @return
	 */
	public static int getHour24() {
		return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 昨天
	 * @param c
	 * @return
	 */
	public static Calendar yesterday(Calendar c) {
		long offset = 1 * 24 * 60 * 60 * 1000;
		c.setTimeInMillis(c.getTimeInMillis() - offset);
		return c;
	}

	/**
	 * 当前时间的昨天
	 * @return
	 */
	public static Calendar yesterday() {
		long offset = 1 * 24 * 60 * 60 * 1000;
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(c.getTimeInMillis() - offset);
		return c;
	}

	/**
	 * 明天
	 * @param c
	 * @return
	 */
	public static Calendar tomorrow(Calendar c) {
		long offset = 1 * 24 * 60 * 60 * 1000;
		c.setTimeInMillis(c.getTimeInMillis() + offset);
		return c;
	}

	/**
	 * 当前时间的明天
	 * @return
	 */
	public static Calendar tomorrow() {
		long offset = 1 * 24 * 60 * 60 * 1000;
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(c.getTimeInMillis() + offset);
		return c;
	}

	/**
	 * Date类型转换到Calendar类型
	 * @param d
	 * @return
	 */
	public static Calendar Date2Calendar(Date d) {
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		return c;
	}

	/**
	 * Calendar类型转换到Date类型
	 * @param c
	 * @return
	 */
	public static Date Calendar2Date(Calendar c) {
		return c.getTime();
	}

	/**
	 * 计算两个日期之间相差的天数
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int daysBetweenDate(Date startDate, Date endDate) {
		Long interval = endDate.getTime() - startDate.getTime();
		interval = interval / (24 * 60 * 60 * 1000);
		return interval.intValue();
	}
	/**
	 * 计算两个日期的小时
	 * @param endDate
	 * @param nowDate
	 * @return
	 */
	public static String getDatePoor(Date endDate, Date nowDate,int scale) {
		
	    long nd = 1000 * 24 * 60 * 60;
	    long nh = 1000 * 60 * 60;
	    long nm = 1000 * 60;
	    // long ns = 1000;
	    // 获得两个时间的毫秒时间差异
	    long diff = endDate.getTime() - nowDate.getTime();
	    // 计算差多少天
	    long day = diff / nd;
	    // 计算差多少小时
	    double hour = diff % nd / nh;
	    // 计算差多少分钟
	    double min = diff % nd % nh / nm;
	    // 计算差多少秒//输出结果
	    // long sec = diff % nd % nh % nm / ns;
	    double reh =MathExtend.add(MathExtend.add(MathExtend.multiply(day,24), Double.parseDouble(MathExtend.divide(min,60))),hour);
	    String style = "#0.";
	    for(int i=0;i<scale;i++){
	    	style = style+"0";
	    }
	    DecimalFormat df1 = new DecimalFormat(style);  
	    String str = df1.format(reh);
	    return str;
	}
	/**
	 * 计算两个日期的小时
	 * @param endDate
	 * @param nowDate
	 * @return
	 * @throws ParseException 
	 */
	public static String getDatePoor(String endDatestr, String nowDatestr,int scale) throws ParseException {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date endDate = sdf.parse(endDatestr);
		Date nowDate = sdf.parse(nowDatestr);
	    long nd = 1000 * 24 * 60 * 60;
	    long nh = 1000 * 60 * 60;
	    long nm = 1000 * 60;
	    // long ns = 1000;
	    // 获得两个时间的毫秒时间差异
	    long diff = endDate.getTime() - nowDate.getTime();
	    // 计算差多少天
	    long day = diff / nd;
	    // 计算差多少小时
	    double hour = diff % nd / nh;
	    // 计算差多少分钟
	    double min = diff % nd % nh / nm;
	    // 计算差多少秒//输出结果
	    // long sec = diff % nd % nh % nm / ns;
	    double reh =MathExtend.add(MathExtend.add(MathExtend.multiply(day,24), Double.parseDouble(MathExtend.divide(min,60))),hour);
	    String style = "#0.";
	    for(int i=0;i<scale;i++){
	    	style = style+"0";
	    }
	    DecimalFormat df1 = new DecimalFormat(style);  
	    String str = df1.format(reh);
	    return str;
	}
	/**
	 * 计算两个日期的分钟
	 * @param endDate
	 * @param nowDate
	 * @return
	 * @throws ParseException 
	 */
	public static String getDatePoorForMin(String endDatestr, String nowDatestr,int scale) throws ParseException {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date endDate = sdf.parse(endDatestr);
		Date nowDate = sdf.parse(nowDatestr);
	    long nd = 1000 * 24 * 60 * 60;
	    long nh = 1000 * 60 * 60;
	    long nm = 1000 * 60;
	    // long ns = 1000;
	    // 获得两个时间的毫秒时间差异
	    long diff = endDate.getTime() - nowDate.getTime();
	    // 计算差多少天
	    long day = diff / nd;
	    // 计算差多少小时
	    double hour = diff % nd / nh;
	    // 计算差多少分钟
	    double min = diff % nd % nh / nm;
	    // 计算差多少秒//输出结果
	    // long sec = diff % nd % nh % nm / ns;
	    double reh =MathExtend.add(MathExtend.add(MathExtend.multiply(day,1440), MathExtend.multiply(hour,60)),min);
	    String style = "#0.";
	    for(int i=0;i<scale;i++){
	    	style = style+"0";
	    }
	    DecimalFormat df1 = new DecimalFormat(style);  
	    String str = df1.format(reh);
	    return str;
	}
	

	/**
	 * 日期加减
	 * @param date 起始日期
	 * @param formatCaseNum 日期格式
	 * @param calendarType 日期计算方式Calender常量(YEAR：加年,MONTH：加月,DATE：加天,HOUR：加小时,MINUTE:分钟,SECOND：加秒)
	 * @param num 需要加减的数量
	 * @return
	 * @throws Exception
	 */
	static public String addDate(String date, int formatCaseNum, int calendarType, int num) {
		SimpleDateFormat format = null;
		Calendar calendar = Calendar.getInstance();
		try {
			format = getDateFormat(formatCaseNum);
			calendar.setTime(format.parse(date));
			calendar.add(calendarType, num);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return format.format(calendar.getTime());
	}

	/**
	 * 判断是否是周末
	 * @param date
	 * @return
	 */
	public static boolean isWeekend(String d) {
		return isWeekend(parseDate(d, yyyy_MM_dd));
	}

	public static boolean isWeekend(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int day = c.get(Calendar.DAY_OF_WEEK);
		if (day == 1 || day == 7) {
			return true;
		}
		return false;
	}

	/**
	 * 给定日期是第几季度
	 * @param date
	 * @return
	 */
	public static int getQuarter(Date date) {
		int quarter = 0;
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int month = getMonth(c);
		if (month >= 0 && month <= 2) {
			quarter = 1;
		} else if (month >= 3 && month <= 5) {
			quarter = 2;
		} else if (month >= 6 && month <= 8) {
			quarter = 3;
		} else if (month >= 9 && month <= 11) {
			quarter = 4;
		}
		return quarter;
	}

	/**
	 * 判断某个日期是否在某个日期范围 
	 * @param beginDate
	 * @param endDate
	 * @param src
	 * @return
	 */
	public static boolean isBetween(Date beginDate, Date endDate, Date src) {
		return beginDate.before(src) && endDate.after(src);
	}

	/**
	 * 比较2个日期
	 * @param beginDate
	 * @param endDate
	 * @param format
	 * @return
	 * @throws ParseException
	 */
	public static int compareDate(String dt1, String dt2, int format) {
		int num = 0;
		Date date1;
		Date date2;
		date1 = parseDate(dt1, format);
		date2 = parseDate(dt2, format);
		if (date1.after(date2)) {
			num = 1;
		} else if (date1.before(date2)) {
			num = -1;
		}
		return num;
	}

	/**
	 * 获得两个时间段内的所有日期
	 * 
	 * @param d1
	 * @param d2
	 * @return
	 * @throws ParseException
	 * @throws java.text.ParseException
	 */
	public static List<String> getBetweenDate(String d1, String d2) throws ParseException, java.text.ParseException {
		List<String> v = new ArrayList<String>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		GregorianCalendar gc1 = new GregorianCalendar(), gc2 = new GregorianCalendar();
		gc1.setTime(sdf.parse(d1));
		gc2.setTime(sdf.parse(d2));
		if (gc1.after(gc2)) {
			GregorianCalendar swap = gc1;
			gc1 = gc2;
			gc2 = swap;
		}
		do {
			GregorianCalendar gc3 = (GregorianCalendar) gc1.clone();
			v.add(sdf.format(gc3.getTime()));
			gc1.add(Calendar.DAY_OF_MONTH, 1);
		} while (!gc1.after(gc2));
		return v;
	}
	/**
	 * 获取指定月份的第一天日期
	 * @param yearMonth-MM
	 * @return
	 */
	public static String getMonthFirstDay(String yearMonth){
		return yearMonth+"-01";
	}
	/**
	 * 获取指定月份的最后一天日期
	 * @param yearMonth-MM
	 * @return
	 */
	public static String getMonthLastDay(String yearMonth){
		String s = DateTimeUtil.addDate(yearMonth+"-01", 0,Calendar.MONTH,1);
		String lastDay = DateTimeUtil.addDate(s, 0, Calendar.DATE,-1);
		return lastDay;
	}
	
	/**
	 * 根据年份返回每季度最后一天日期或者每季度第一天日期
	 * @param year：年份
	 * @param quarter:季度
	 * @param type:first:度第一天日期，last：季度最后一天日期
	 * @return 
	 * @throws Exception
	 */
	public static String endDateofTheQuarter(String year, String quarter, String type){
		String edate = "";
		String sdate = "";
		if (quarter.equals("1")) {// 第一季度
			sdate = year + "-01-01";
			edate = year + "-03-31";
		} else if (quarter.equals("2")) {// 第二季度
			sdate = year + "-04-01";
			edate = year + "-06-30";
		} else if (quarter.equals("3")) {// 第三季度
			sdate = year + "-07-01";
			edate = year + "-09-30";
		} else if (quarter.equals("4")) {// 第四季度
			sdate = year + "-10-01";
			edate = year + "-12-31";
		}
		if (type.equals("first")) {
			return sdate;
		} else {
			return edate;
		}
	}
	
	/**
	 * 获取当前时刻 （早上，上午，下午，晚上）
	 * @return
	 */
	public static String getMonment(){
		String s = "";
		int hour = getHour24();
		if(hour>=0 && hour <6){
			s = "早上";
		}else if(hour>6 && hour <=12){
			s = "上午";
		}else if(hour>12 && hour <=18){
			s = "下午";
		}else if(hour>18 && hour <=24){
			s = "晚上";
		}
		return s;
	}
	/**
	 * 根据年和月获取每个月的每天数字，并按照日历格式输出
	 * @param year
	 * @param month
	 * @return
	 */
	public static String[] getMonthDays(int year,int month){
		String a[]=new String[42];
		Calendar date=Calendar.getInstance();
		date.set(year,month-1,1);
		int week=date.get(Calendar.DAY_OF_WEEK)-1;
		int day=0; 
		//判断大月份  
		if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){
			day=31;
		}
		//判断小月
		if(month==4||month==6||month==9||month==11){
			day=30;
		}
		//判断平年与闰年
		if (month == 2) {
			if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
				day = 29;
			} else {
				day = 28;
			}
		}
		for (int i = week, n = 1; i < week + day; i++) {
			a[i] = String.valueOf(n);
			n++;
		}
		return a;
	}
	/**
	 * 获取前几分钟的时间
	 * 
	 */
	public static String getBeforTime(int m){
		Calendar beforeTime = Calendar.getInstance();
		beforeTime.add(Calendar.MINUTE, -m);
		Date beforeD = beforeTime.getTime();
		return formatDate(beforeD, yyyy_MM_dd_HH_mm_ss);
	}
	/**
	 * 获取前一个月的第一天
	 */
	public static String getBerforMonthStartDay(int m){
		Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH,1);
        return formatDate(Calendar2Date(calendar), m);
	}
	/**
	 * 获取前一个月的最后一天
	 */
	public static String getBerforMonthEndDay(int m){
		Calendar calendar = Calendar.getInstance();
        //calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DAY_OF_MONTH,0);
        return formatDate(Calendar2Date(calendar), m);
	}
	/**
	 * 获取前一个月的前一个月的第一天
	 */
	public static String getBerforMonth2StartDay(int m){
		Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -2);
        calendar.set(Calendar.DAY_OF_MONTH,1);
        return formatDate(Calendar2Date(calendar), m);
	}
	/**
     * 通过时间秒毫秒数判断两个时间的间隔
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(Date date1,Date date2)
    {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
        return days;
    }
    /**
     * 通过时间秒毫秒数判断两个时间的间隔
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(String datestr1,String datestr2)
    {
    	Date date1 = parseDate(datestr1, yyyy_MM_dd);
    	Date date2 = parseDate(datestr2, yyyy_MM_dd);
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
        return days;
    }
    /**
     * 获取前几天
     * @param num
     * @return
     */
    public static String beforDay(String datestr,int num){
    	Date date = parseDate(datestr, yyyy_MM_dd);
    	Calendar calendar1 =Date2Calendar(date);
    	calendar1.add(Calendar.DATE, -num);
    	return formatDate(Calendar2Date(calendar1), yyyy_MM_dd);
    }
   
    /**
	 * 用于获取明天的日期（字符串类型）
	 * @param today
	 * @return
	 */
	public static String getTomorrow (String today){
		Calendar startCalendar=DateTimeUtil.parseCalendar(today,0);
		Calendar tomorrow  = DateTimeUtil.tomorrow(startCalendar);
		Date  tomorrowDate= DateTimeUtil.Calendar2Date(tomorrow);
		String tomorrowString = DateTimeUtil.formatDate(tomorrowDate,0);
		return tomorrowString;
	}
}
